package au.com.mason.propertyTracker.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import au.com.mason.propertyTracker.dao.MonitorDAO;
import au.com.mason.propertyTracker.dao.PropertyDAO;
import au.com.mason.propertyTracker.dao.SuburbDAO;
import au.com.mason.propertyTracker.domain.Property;
import au.com.mason.propertyTracker.domain.SaleProperty;
import au.com.mason.propertyTracker.domain.Search;
import au.com.mason.propertyTracker.domain.Status;
import au.com.mason.propertyTracker.domain.Suburb;
import au.com.mason.propertyTracker.dto.SearchParameters;
import au.com.mason.propertyTracker.util.HttpClientWrapper;
import au.com.mason.propertyTracker.util.RealEstateResponseParser;

@Service
public class MonitorSuburbService {
	private static final Log LOG = LogFactory.getLog(MonitorSuburbService.class);
	private static final boolean DEBUG = false;
	
	private MonitorDAO monitorDAO;
	private PropertyDAO propertyDAO;
	private SuburbDAO suburbDAO;

	@Autowired
	public MonitorSuburbService(MonitorDAO monitorDAO, PropertyDAO propertyDAO, SuburbDAO suburbDAO) {
		this.monitorDAO = monitorDAO;
		this.propertyDAO = propertyDAO;
		this.suburbDAO = suburbDAO;
	}
	
	public void findNew() {
		LOG.info("****************************** Monitor Results for - " + new Date());

		process(false, false);
		process(true, false);
	}

	private void process(boolean isRental, boolean includeFull) {
		HttpClientWrapper httpClientWrapper = new HttpClientWrapper();
		List<Search> monitors = monitorDAO.getMonitors(isRental, includeFull);
		
		for (Search monitor : monitors) {
			httpClientWrapper.initAndExecute(monitor.getUrl());
			
			RealEstateResponseParser parser = new RealEstateResponseParser(httpClientWrapper.getResponse());
			
			int newProperties = 0;
			List<String> urls = parser.getUrls();
			
			for (String propertyUrl : urls) {
				try {
					BigDecimal propertyId = null;
					if (propertyUrl.indexOf("?") != -1) {
						propertyId = new BigDecimal(propertyUrl.substring(propertyUrl.lastIndexOf("-") + 1, propertyUrl.indexOf("?")));
					}
					else {
						propertyId = new BigDecimal(propertyUrl.substring(propertyUrl.lastIndexOf("-") + 1));
					}
					Property property = propertyDAO.findByPropertyId(propertyId);
					
					if (property == null) {
						httpClientWrapper.initAndExecute(propertyUrl);
						RealEstateResponseParser propertyParser = new RealEstateResponseParser(httpClientWrapper.getResponse());
						
						newProperties++;
						SaleProperty newProperty = propertyParser.getSaleProperty(propertyUrl);
//						if (monitor.isRental()) {
//							newProperty.setRent(prices[0]);
//							newProperty.setRental(true);
//						}
						newProperty.setSuburb(suburbDAO.getSuburb(propertyParser.getSuburbName()));
						
						newProperty.setRealEstatePropertyId(propertyId);
						newProperty.setDateListed(new Date());
						
						propertyDAO.save(newProperty);
					}
				}
				catch (Exception e) {
					System.out.println(e.getMessage() + " for " + propertyUrl);
					if (DEBUG) {
						e.printStackTrace();
					}
				}
			}

			//TODO: write out summary of number of properties found and for which suburbs
			
		}
	}

	public void determineChanged() {
		HttpClientWrapper httpClientWrapper = new HttpClientWrapper();
		SearchParameters searchParameters = new SearchParameters();
		searchParameters.setMonitor(true);
		List<Property> properties = propertyDAO.filterProperties(null, searchParameters);
		int removed = 0;
		int sold = 0;
		int underContract = 0;
		int removedRentals = 0;
		
		int count = 0;
		System.out.println("***************** processing determine change property");
		for (Property property : properties) {
			try {
				if (!property.isRemoved() && !property.isSold()) {
					httpClientWrapper.init(property.getUrl());
					
					if (httpClientWrapper.isRemoved(property)) {
						removed++;
						property.setStatus(Status.REMOVED);
						property.setStatusDate(new Date());
						propertyDAO.update(property);
					}
					else {
						String response = httpClientWrapper.getResponse();
						if (response == null) {
							System.out.println("No response found for property with url " + property.getUrl());
						}
						else {
							RealEstateResponseParser parser = new RealEstateResponseParser(response);
							if (parser.isUnderContract()) {
								if (!property.isUnderContract()) {
									underContract++;
									//System.out.println(response.toString());
									property.setStatus(Status.UNDER_CONTRACT);
									property.setStatusDate(new Date());
									propertyDAO.update(property);
								}
							}
							else if (parser.isSold()) {
								sold++;
								property.setStatus(Status.SOLD);
								property.setStatusDate(new Date());
								propertyDAO.update(property);
							}
						}
					}
					count++;
					
					if (count%10 == 0) System.out.println("processed: " + count);
				}
			}
			catch (Exception e) {
				System.out.println(e.getMessage() + " for " + property.getUrl());
				if (DEBUG) {
					e.printStackTrace();
				}
			}
		}
		
		searchParameters.setRental(true);
		searchParameters.setMonitor(true);
		List<Property> rentals = propertyDAO.filterProperties(null, searchParameters);
		
		count = 0;
		System.out.println("***************** processing determine change rental");
		for (Property property : rentals) {
			try {
				if (!property.isRemoved()) {
					httpClientWrapper.init(property.getUrl());
					if (httpClientWrapper.isRemoved(property)) {
						removedRentals++;
						property.setStatus(Status.REMOVED);
						property.setStatusDate(new Date());
						propertyDAO.update(property);
					}
					count++;
					
					if (count%10 == 0) System.out.println("processed: " + count);
				}
			}
			catch (Exception e) {
				System.out.println(e.getMessage() + " for " + property.getUrl());
				if (DEBUG) {
					e.printStackTrace();
				}
			}
		}
		
		LOG.info("number of sold properties - " + sold);
		LOG.info("number of under contract properties - " + underContract);
		LOG.info("number of removed properties - " + removed);
		LOG.info("number of removed rental properties - " + removedRentals);
	}
	
}
